package bgapi

import (
	"bgs/db"
	sqlc "bgs/db/sqlc"
	userService "bgs/service/user"
	"bgs/util"
	"bytes"
	"context"
	"encoding/json"
	"fmt"

	"github.com/nsqio/go-nsq"
	"go.uber.org/zap"
)

var (
	lastBrandFollowMessage *BrandFollowMessage = nil
)

// BrandFollowMessage BrandFollow message struct
type BrandFollowMessage struct {
	TS   int64 `json:"ts"`
	Data struct {
		// 用户
		UserID int64 `json:"user_id"`
		// 关注的品牌
		FollowedBrandID int64 `json:"followed_brand_id"`
		// 关注时间
		Followed int64 `json:"followed"`
	} `json:"data"`
}

// BrandFollowHandler BrandFollow message handler
type BrandFollowHandler struct {
	dao         *db.PgDao
	slog        *zap.SugaredLogger
	userService *userService.UserServiceImp
}

// NewBrandFollowHandler create a new handler for BrandFollow
func NewBrandFollowHandler(
	pgdao *db.PgDao,
	slog *zap.SugaredLogger,
	userService *userService.UserServiceImp,
) *BrandFollowHandler {
	return &BrandFollowHandler{
		dao:         pgdao,
		slog:        slog.With("module", "BrandFollowHandler"),
		userService: userService,
	}
}

// HandleMessage implements the Handler interface.
func (h *BrandFollowHandler) HandleMessage(m *nsq.Message) error {
	if len(m.Body) == 0 {
		// Returning nil will automatically send a FIN command to NSQ to mark the message as processed.
		return nil
	}

	h.slog.Infof("BrandFollowMessage=>%s", string(m.Body))

	v := &BrandFollowMessage{}
	if decodeErr := json.NewDecoder(bytes.NewReader(m.Body)).Decode(v); decodeErr != nil {
		return fmt.Errorf("无法解析信息[BrandFollowMessage]: %v", decodeErr)
	}
	if lastBrandFollowMessage != nil && lastBrandFollowMessage.TS >= v.TS {
		h.slog.Infof("过时的消息: lastBrandFollowMessage.TS:%v,v.TS:%v", lastBrandFollowMessage.TS, v.TS)
		return nil
	}

	userID := v.Data.UserID
	ctx := context.Background()

	err := h.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
		_, err = h.dao.Q.UpsertBrandFollow(ctx, sqlc.UpsertBrandFollowParams{
			UserID:          userID,
			FollowedBrandID: v.Data.FollowedBrandID,
			Followed:        util.MsToGoTime(v.Data.Followed),
		})
		if err != nil {
			return err
		}
		h.slog.Infof("a BrandFollowHandler-插入/更新品牌关注关系 ok")

		err = h.userService.UpdateUserStatSinceFollowBrand(ctx, q, userID)
		if err != nil {
			return err
		}
		h.slog.Infof("b BrandFollowHandler-用户关注品牌统计到(UserStat) ok")
		return
	})

	if err != nil {
		return err
	}
	lastBrandFollowMessage = v
	// Returning a non-nil error will automatically send a REQ command to NSQ to re-queue the message.
	return nil
}
